{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "email_conversation = \"\"\"From: 테디 (teddy@teddynote.com)\n",
    "To: 이은채 대리님 (eunchae@teddyinternational.me)\n",
    "Subject: RAG 솔루션 시연 관련 미팅 제안\n",
    "\n",
    "안녕하세요, 이은채 대리님,\n",
    "\n",
    "저는 테디노트의 테디입니다. 최근 귀사에서 AI를 활용한 혁신적인 솔루션을 모색 중이라는 소식을 들었습니다. 테디노트는 AI 및 RAG 솔루션 분야에서 다양한 경험과 노하우를 가진 기업으로, 귀사의 요구에 맞는 최적의 솔루션을 제공할 수 있다고 자부합니다.\n",
    "\n",
    "저희 테디노트의 RAG 솔루션은 귀사의 데이터 활용을 극대화하고, 실시간으로 정확한 정보 제공을 통해 비즈니스 의사결정을 지원하는 데 탁월한 성능을 보입니다. 이 솔루션은 특히 다양한 산업에서의 성공적인 적용 사례를 통해 그 효과를 입증하였습니다.\n",
    "\n",
    "귀사와의 협력 가능성을 논의하고, 저희 RAG 솔루션의 구체적인 기능과 적용 방안을 시연하기 위해 미팅을 제안드립니다. 다음 주 목요일(7월 18일) 오전 10시에 귀사 사무실에서 만나 뵐 수 있을까요?\n",
    "\n",
    "미팅 시간을 조율하기 어려우시다면, 편하신 다른 일정을 알려주시면 감사하겠습니다. 이은채 대리님과의 소중한 만남을 통해 상호 발전적인 논의가 이루어지길 기대합니다.\n",
    "\n",
    "감사합니다.\n",
    "\n",
    "테디\n",
    "테디노트 AI 솔루션팀\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pydantic import BaseModel, Field\n",
    "\n",
    "\n",
    "# 이메일 본문으로부터 주요 엔티티 추출\n",
    "class EmailSummary(BaseModel):\n",
    "    person: str = Field(description=\"메일을 보낸 사람\")\n",
    "    company: str = Field(description=\"메일을 보낸 사람의 회사 정보\")\n",
    "    email: str = Field(description=\"메일을 보낸 사람의 이메일 주소\")\n",
    "    subject: str = Field(description=\"메일 제목\")\n",
    "    summary: str = Field(description=\"메일 본문을 요약한 텍스트\")\n",
    "    date: str = Field(description=\"메일 본문에 언급된 미팅 날짜와 시간\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "## LCEL 구조\n",
    "\n",
    "# chain = prompt | llm | output_parser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(temperature=0, model_name=\"gpt-4o\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.output_parsers import PydanticOutputParser\n",
    "\n",
    "# PydanticOutputParser 생성\n",
    "output_parser = PydanticOutputParser(pydantic_object=EmailSummary)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "prompt = PromptTemplate.from_template(\n",
    "    \"\"\"\n",
    "You are a helpful assistant. Please answer the following questions in KOREAN.\n",
    "\n",
    "#QUESTION:\n",
    "다음의 이메일 내용 중에서 주요 내용을 추출해 주세요.\n",
    "\n",
    "#EMAIL CONVERSATION:\n",
    "{email_conversation}\n",
    "\n",
    "#FORMAT:\n",
    "{format}\n",
    "\"\"\"\n",
    ")\n",
    "\n",
    "# format 에 PydanticOutputParser의 부분 포맷팅(partial) 추가\n",
    "prompt = prompt.partial(format=output_parser.get_format_instructions())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 체인 생성\n",
    "chain = prompt | llm | output_parser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 체인 실행\n",
    "answer = chain.invoke({\"email_conversation\": email_conversation})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "테디노트의 테디가 이은채 대리님에게 RAG 솔루션 시연을 위한 미팅을 제안합니다. 미팅은 다음 주 목요일(7월 18일) 오전 10시에 귀사 사무실에서 진행되기를 희망하며, 다른 일정이 필요하면 조율을 요청합니다.\n"
     ]
    }
   ],
   "source": [
    "print(answer.summary)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "EmailSummary(person='테디', company='테디노트', email='teddy@teddynote.com', subject='RAG 솔루션 시연 관련 미팅 제안', summary='테디노트의 테디가 이은채 대리님에게 RAG 솔루션 시연을 위한 미팅을 제안합니다. 미팅은 다음 주 목요일(7월 18일) 오전 10시에 귀사 사무실에서 진행되기를 희망하며, 다른 일정이 필요하면 조율을 요청합니다.', date='다음 주 목요일(7월 18일) 오전 10시')"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "answer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 검색: SERP API"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "참고: https://serpapi.com/integrations/python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"SERPAPI_API_KEY\"] = \"발급 받은 SERPAPI API 키를 입력하세요\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.utilities import SerpAPIWrapper\n",
    "\n",
    "params = {\"engine\": \"google\", \"gl\": \"kr\", \"hl\": \"ko\", \"num\": \"3\"}\n",
    "\n",
    "search = SerpAPIWrapper(params=params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'teddy@teddynote.com'"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "answer.email"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'테디 테디노트 teddy@teddynote.com'"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "query = f\"{answer.person} {answer.company} {answer.email}\"\n",
    "query"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "search_result = search.run(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "search_result = eval(search_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "list"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(search_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 검색 결과\n",
    "search_result_string = \"\\n\".join(search_result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "EmailSummary(person='테디', company='테디노트', email='teddy@teddynote.com', subject='RAG 솔루션 시연 관련 미팅 제안', summary='테디노트의 테디가 이은채 대리님에게 RAG 솔루션 시연을 위한 미팅을 제안합니다. 미팅은 다음 주 목요일(7월 18일) 오전 10시에 귀사 사무실에서 진행되기를 희망하며, 다른 일정이 필요하면 조율을 요청합니다.', date='다음 주 목요일(7월 18일) 오전 10시')"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "answer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "report_prompt = PromptTemplate.from_template(\n",
    "    \"\"\"당신은 이메일의 주요 정보를 바탕으로 요약 정리해 주는 전문가 입니다.\n",
    "당신의 임무는 다음의 이메일 정보를 바탕으로 보고서 형식의 요약을 작성하는 것입니다.\n",
    "주어진 정보를 기반으로 양식(format)에 맞추어 요약을 작성해 주세요.\n",
    "\n",
    "#Information:\n",
    "- Sender: {sender}\n",
    "- Additional Information about sender: {additional_information}\n",
    "- Company: {company}\n",
    "- Email: {email}\n",
    "- Subject: {subject}\n",
    "- Summary: {summary}\n",
    "- Date: {date}\n",
    "\n",
    "#Format(in markdown format):\n",
    "🙇‍♂️ 보낸 사람:\n",
    "- (보낸 사람의 이름, 회사 정보)\n",
    "\n",
    "📧 이메일 주소:\n",
    "- (보낸 사람의 이메일 주소)\n",
    "\n",
    "😍 보낸 사람과 관련하여 검색된 추가 정보:\n",
    "- (검색된 추가 정보)\n",
    "\n",
    "✅ 주요 내용:\n",
    "- (이메일 제목, 요약)\n",
    "\n",
    "⏰ 일정:\n",
    "- (미팅 날짜 및 시간)\n",
    "\n",
    "#Answer:\"\"\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.output_parsers import StrOutputParser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [],
   "source": [
    "report_chain = (\n",
    "    report_prompt | ChatOpenAI(model=\"gpt-4-turbo\", temperature=0) | StrOutputParser()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "report_response = report_chain.invoke(\n",
    "    {\n",
    "        \"sender\": answer.person,\n",
    "        \"additional_information\": search_result_string,\n",
    "        \"company\": answer.company,\n",
    "        \"email\": answer.email,\n",
    "        \"subject\": answer.subject,\n",
    "        \"summary\": answer.summary,\n",
    "        \"date\": answer.date,\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🙇‍♂️ 보낸 사람:\n",
      "- 테디, 테디노트\n",
      "\n",
      "📧 이메일 주소:\n",
      "- teddy@teddynote.com\n",
      "\n",
      "😍 보낸 사람과 관련하여 검색된 추가 정보:\n",
      "- 테디노트는 데이터 분석, 머신러닝, 딥러닝, LLM에 대한 내용을 다루며, 연구보다는 개발에 관심이 많은 테디가 운영합니다. 테디노트는 다양한 데이터와 인공지능 관련 정보를 제공하는 플랫폼입니다.\n",
      "\n",
      "✅ 주요 내용:\n",
      "- 제목: RAG 솔루션 시연 관련 미팅 제안\n",
      "- 요약: 테디노트의 테디가 이은채 대리님에게 RAG 솔루션 시연을 위한 미팅을 제안합니다. 미팅은 다음 주 목요일(7월 18일) 오전 10시에 귀사 사무실에서 진행되기를 희망하며, 다른 일정이 필요하면 조율을 요청합니다.\n",
      "\n",
      "⏰ 일정:\n",
      "- 다음 주 목요일(7월 18일) 오전 10시\n"
     ]
    }
   ],
   "source": [
    "print(report_response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain-kr--BePIR02-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
